using System.Collections.Concurrent;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using Godot;
using System.Collections.Generic;
using Box.GameCore;
using Box.Base;


namespace Box.DefaultSandbox {
    public partial class Sandbox : Node2D {
        StorageSystem storage = Game.Instance.StorageSystem;
        public static long ToSandboxRegionIndex(int x,int y) {
            return ((long)x) | (((long)y) >> 32);
        }

        public Vector2i RegionLoadCenter = new Vector2i();
        public Vector2i RegionLoadTopLeft;
        public Vector2i RegionLoadButtomRight;
        public int RegionLoadRadius = 8;

        public Task RegionControlThread;

        public Dictionary<long,SandboxRegion> Regions = new Dictionary<long, SandboxRegion>();

        
        public ConcurrentQueue<SandboxRegion> RegionUnloadQueue = new ConcurrentQueue<SandboxRegion>();
        public ConcurrentQueue<long> RegionLoadQueue = new ConcurrentQueue<long>();

        //区块每次读取和写入的数量
        protected int RegionControlFrameSize = 18;

        public void StartRegionControlThread() {
            RegionControlThread = Task.Run(()=>{
                while(IsInsideTree()) {
                    Archive archive = storage.CurrentArchive;
                    if(archive != null) {
                        for(int i = 0;i<RegionControlFrameSize;i++) {
                            SandboxRegion unload_region;
                            if(RegionUnloadQueue.TryDequeue(out unload_region)) {
                                UnloadRegion(archive,unload_region);
                            }
                            long load_region_index;
                            if(RegionLoadQueue.TryDequeue(out load_region_index)) {
                                SandboxRegion region = LoadRegion(archive,load_region_index);

                            }
                        }
                    }
                }
            });
        }

        protected string GetRegionStorageFileName(SandboxRegion region) {
            long index = ToSandboxRegionIndex(region.X,region.Y);
            return $"{index}.region";
        }

        protected string GetRegionStorageFileName(long index) {
            return $"{index}.region";
        }

        protected void UnloadRegion(Archive archive,SandboxRegion region) {
            using(GDIOStorageFile file = new GDIOStorageFile()) {
                file.Open($"{archive.Path}/regions/{GetRegionStorageFileName(region)}",StorageFileMode.Write);
                file.Write(region);
            }
        }

        protected SandboxRegion LoadRegion(Archive archive,long index) {
            using(GDIOStorageFile file = new GDIOStorageFile()) {
                file.Open($"{archive.Path}/regions/{GetRegionStorageFileName(index)}",StorageFileMode.Write);
                return file.ReadStorageObject() as SandboxRegion;
            }
        }

        public override void _EnterTree() {
            StartRegionControlThread();
        }

        public SandboxRegion GetRegion(int x,int y) {
            long index = ToSandboxRegionIndex(x,y);
            if(!Regions.ContainsKey(index)) return null;
            return Regions[index];
        }

        public SandboxRegion GetRegion(long index) {
            if(!Regions.ContainsKey(index)) return null;
            return Regions[index];
        }

        protected static bool IsBoxIncludePoint(Vector2i top,Vector2i buttom,Vector2i p) {
            return p > top && p < buttom;
        }

        public void SetLoadCenter(Vector2i new_center) {
            if(RegionLoadCenter == new_center) return;
            Vector2i load_size = new Vector2i(RegionLoadRadius,RegionLoadRadius);
            Vector2i new_top_left = new_center - load_size;
            Vector2i new_buttom_right = new_center + load_size;

            for(int y = new_top_left.y;y < new_buttom_right.y;y++) {
                for(int x = new_top_left.x;y < new_buttom_right.x;x++) {
                    if(!IsBoxIncludePoint(RegionLoadTopLeft,RegionLoadButtomRight,new Vector2i(x,y))) {
                        RegionLoadQueue.Enqueue(ToSandboxRegionIndex(x,y));
                    }
                }
            }

            RegionLoadCenter = new_center;
            RegionLoadTopLeft = new_top_left;
            RegionLoadButtomRight = new_buttom_right;
        }

        public override void _Process(double delta)
        {
            
        }
    }
}